﻿using Numbers.Arithmatic;
using Numbers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Silverlight.Testing;
namespace t_Numbers
{
    
    
    /// <summary>
    ///This is a test class for t_Addition and is intended
    ///to contain all t_Addition Unit Tests
    ///</summary>
    [TestClass]
    public class t_Addition
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestMethod]
        public void TestAdditionCTor()
        {
            Value r = new Value(), v1 = new Value();
            Addition.Create(r, new Value[] { v1 });

            Value r2 = new Value(), v2 = new Value() { Val = 5.0 };
            Addition.Create(r2, new Value[] {v2});
            Assert.AreEqual(5.0, v2.Val, "Value is still correct!");
            Assert.AreEqual(5.0, r2.Val, "The value has not been set!");
        }

        [TestMethod]
        public void TestSingleEqual()
        {
            Value r = new Value(), v1 = new Value();
            Addition.Create(r, new Value[] { v1 });

            Assert.AreEqual(0.0, r.Val, "Should still be at zero");
            v1.Val = 5.0;
            Assert.AreEqual(5.0, r.Val, "R should have changed!");
            r.Val = 10.0;
            Assert.AreEqual(10.0, r.Val, "R should hav echanged to 10 when we set it");
            Assert.AreEqual(10.0, v1.Val, "value should have changed too!");
        }

        [TestMethod]
        public void TestTwoAdds()
        {
            Value r = new Value(), v1 = new Value(), v2 = new Value();
            Addition.Create(r, new Value[] { v1, v2 });

            Assert.AreEqual(0.0, r.Val, "Value is equal");
            r.Val = 10.0;
            Assert.AreEqual(10.0, r.Val, "Result should have stuck to 10 - but didn't - something blew!");
            Assert.AreEqual(5.0, v1.Val, "Expected the two to be split");
            Assert.AreEqual(5.0, v2.Val, "Expected the two to be split!");

            v2.Val = 10.0;
            Assert.AreEqual(15.0, r.Val, "Expecting the total to increase!");
            r.Val = 30.0;
            Assert.AreEqual(10.0, v1.Val, "Expecting the first dude to double");

            v2.Val = 0.0;
            r.Val = 30.0;
            Assert.AreEqual(30.0, v1.Val, "Expecting all to go to v1 since v2 is zero");

        }

        [TestMethod]
        public void TestTwoAddsTS()
        {
            Value r = new Value(), v1 = new Value(), v2 = new Value();
            Addition.Create(r, new Value[] { v1, v2 });

            Assert.AreEqual(r.TransactionManager, v1.TransactionManager, "r and v1 TS should be the same");
            Assert.AreEqual(r.TransactionManager, v2.TransactionManager, "r and v2 TS should be the same");
            Assert.IsNotNull(r.TransactionManager, "TS should not be null!");
        }

        [TestMethod]
        public void TestThreeAdds()
        {
            Value r = new Value();
            Value v1 = new Value();
            Value v2 = new Value();
            Value v3 = new Value();

            Addition.Create(r, new Value[] { v1, v2, v3 });

            v1.Val = 10.0;
            Assert.AreEqual(10.0, r.Val, "One set to 10 should match!");
            v2.Val = 20.0;
            Assert.AreEqual(30.0, r.Val, "second operand seems to have failed");
            v3.Val = 30.0;
            Assert.AreEqual(60.0, r.Val, "third operand doesn't seem to be working right");
        }

        [TestMethod]
        public void TestTwoAddsAtOnce()
        {
            Value r1 = new Value("r1");
            Value r2 = new Value("r2");
            Value v1 = new Value("v1");
            Value v2 = new Value("v2");
            Value v3 = new Value("v3");

            Addition.Create(r1, new Value[] { v1, v2, v3 });
            Addition.Create(r2, new Value[] { v1, v2 });

            v1.Val = 10.0;
            Assert.AreEqual(10.0, r1.Val, "One set to 10 should match! - r1");
            Assert.AreEqual(10.0, r2.Val, "One set to 10 should match! - r2");
            v2.Val = 20.0;
            Assert.AreEqual(30.0, r1.Val, "second operand seems to have failed - r1");
            Assert.AreEqual(30.0, r2.Val, "second operand seems to have failed - r2");
            v3.Val = 30.0;
            Assert.AreEqual(60.0, r1.Val, "third operand doesn't seem to be working right - r1");
            Assert.AreEqual(30.0, r2.Val, "third operand doesn't seem to be working right - r2");

            /// Try back-propagation
            v1.Val = v2.Val = v3.Val = 0.0;

            r2.Val = 100;
            Assert.AreEqual(100.0, r2.Val, "Transaction or something must have failed - r2 didn't pick up its correctly value!");
            Assert.AreEqual(50.0, v1.Val, "Expecting half to have gone into v1");
            Assert.AreEqual(50.0, v2.Val, "Expecting half to have gone into v2");
            Assert.AreEqual(100, r1.Val, "Expecting the sum for r1 to have been correctly updated!");
        }

        [TestMethod]
        [ExpectedException(typeof(System.ArgumentException))]
        public void TestInitialBadConfig()
        {
            Value r = new Value();
            Value m1 = new Value();
            Value m2 = new Value();

            r.MaxValue = 10.0;
            m1.Val = 10.0;
            m2.Val = 10.0;

            Addition.Create(r, new Value[] { m1, m2 });
        }

        [TestMethod]
        public void TestAddTotalZero()
        {
            Value r = new Value();
            Value m1 = new Value();
            Value m2 = new Value();

            Addition.Create(r, new Value[] { m1, m2 });

            m1.Val = 10;
            m2.Val = 20;

            r.Val = 0;
            Assert.AreEqual(0, m1.Val, "operand 1 shoudl be zero after total set to zero");
            Assert.AreEqual(0, m2.Val, "operand 2 shoudl be zero after total set to zero");
        }
    }
}
